import { forwardRef, useCallback, useEffect, useImperativeHandle } from 'react';
import { Field } from '@formily/core';
import { connect, mapProps, useField } from '@formily/react';
import { inbiz } from '@inbiz/render';
import { getMessage, TextWidget } from '@inbiz/react';
import { useEvents } from '@inbiz/utils';
import { InputNumber } from 'antd';
import { defaultProps } from '../../designer/schema';
import api from './api';
import './style.less';
type IProps = {
  value: string;
  readOnly: boolean;
  disabled: boolean;
  inbiz: inbiz;
  title: string;
  minimum: number;
  maximum: number;
  addonAfter: string;
  viewMode?: string;
  callBackEvents?: {
    onBeforeChange?: (v: string) => boolean;
  };
  controlId: string
  emit?: () => void;
} & typeof defaultProps;

const EformNumber = forwardRef((props: IProps, ref) => {
  const {
    callBackEvents,
    emit,
    defaultValueType,
    precision,
    prefix,
    suffix,
    inbiz,
    maxLength,
    maximum,
    minimum,
    title,
    placeholder,
    clearable,
    controlId,
    viewMode,
    ...other
  } = props;
  const isDesigner = inbiz.browser.designer
  const filed = useField<Field>();
  const [configEvents] = useEvents(props.callBackEvents, props.emit);
  useImperativeHandle(
    ref,
    () => ({
      ...api(configEvents, props, filed),
    }),
    [],
  );

  // 自定义验证逻辑
  useEffect(() => {
    filed.setValidatorRule('validator', (value: number, rule: any, ctx: any) => {
      const { maxLength, maximum, minimum } = ctx.field.componentProps;
      if (value === undefined || value === null) {
        return true;
      }
      if (maxLength && value.toString().length > maxLength) {
        return (
          <>
            <TextWidget>EformNumber.validate.maxLengthNumber</TextWidget>
            {maxLength}
          </>
        );
      }
      if (maximum !== undefined && maximum !== null) {
        if (Number(value) > maximum) {
          // return getMessage('EformNumber.validate.maximum') + maximum;
          return (
            <>
              <TextWidget>EformNumber.validate.maximum</TextWidget>
              {maximum}
            </>
          );
        }
      }
      if (minimum !== undefined && minimum !== null) {
        if (Number(value) < minimum) {
          // return getMessage('EformNumber.validate.minimum') + minimum;
          return (
            <>
              <TextWidget>EformNumber.validate.minimum</TextWidget>
              {minimum}
            </>
          );
        }
      }
      return true;
    });
  }, []);

  const formatter = useCallback(
    (value: any, e: any) => {
      return moneyFormat(value, props.formatter, precision, !e.userTyping);
    },
    [props.formatter, precision],
  );
  return viewMode == 'look' ?<div >{(prefix ? prefix : '') + formatter(props.value, {userTyping: false}) + (props.addonAfter ? props.addonAfter : '')}</div>  : <InputNumber
    {...other}
    className={`efromNumber ${props.addonAfter ? 'eformNumberAddon' : ''}`}
    formatter={props.formatter ? formatter : undefined}
    parser={props.formatter ? (value: any) => parser(value!, props.formatter) : undefined}
    prefix={prefix ? prefix : undefined}
    // 数字框编辑界面有hover效果
    style={isDesigner ? { width: '100%', pointerEvents: 'none' } : { width: '100%' }}
    disabled={props.readOnly || props.disabled}
    precision={precision == 0 || precision == undefined ? 0 : precision} // 精度处理，为空为 0 时，不启用精度控制
    placeholder={placeholder}
  />;
});

(EformNumber as typeof EformNumber & IDefaultValueFormat<typeof defaultProps>).defaultValueFormat =
  (props: any): string | void | null => {
    if (props.defaultValue != undefined) {
      if (props.defaultValue === '') {
        return null
      }
      return props.defaultValue;
    }
    return null;
  };

EformNumber.displayName = 'EformNumber';

export default connect(
  EformNumber,
  mapProps((props: IProps) => {
    const others = props;
    others.placeholder = getMessage(props.placeholder);
    return { ...props };
  }),
);
export type { IProps };

function moneyFormat(_value: string | undefined, split = ',', decimal = 0, isDecimal: boolean) {
  /*
    parameter：
    num：格式化目标数字
    decimal：保留几位小数，默认2位
    split：千分位分隔符，默认为,
    moneyFormat(123456789.87654321, 2, ',') // 123,456,789.88
  */
  const value = _value?.toString()
  if (!value) {
    return '';
  }


  const valueStr = value.includes('e') ? Number(value).toLocaleString().replace(/,/g, '') : value;

  const num = Number(value);
  if (isFinite(num)) {
    // num是数字
    if (num === 0) {
      // 为0
      return decimal && isDecimal ? num.toFixed(decimal) : '0';
    } else {
      // 非0
      var res = '';
      var dotIndex = valueStr.indexOf('.');
      if (dotIndex === -1) {
        // 整数
        res =
          valueStr.replace(/(\d)(?=(?:\d{3})+$)/g, `$1${split}`) +
          (decimal && isDecimal ? `.${'0'.repeat(decimal)}` : '');
      } else {
        // 非整数
        // js四舍五入 Math.round()：正数时4舍5入，负数时5舍6入
        // Math.round(1.5) = 2
        // Math.round(-1.5) = -1
        // Math.round(-1.6) = -2
        // 保留decimals位小数

        if (isDecimal) {
          const numStr = String(
            (Math.round(num * Math.pow(10, decimal)) / Math.pow(10, decimal)).toFixed(decimal),
          ); // 四舍五入，然后固定保留2位小数
          const decimals = numStr.slice(dotIndex, dotIndex + decimal + 1); // 截取小数位
          res = numStr.slice(0, dotIndex).replace(/(\d)(?=(?:\d{3})+$)/g, `$1${split}`) + decimals;
        } else {
          const [integer, decimalStr] = valueStr.split('.');
          return integer.replace(/(\d)(?=(?:\d{3})+$)/g, `$1${split}`) + '.' + decimalStr;
        }
      }
      return res;
    }
  } else {
    return value.slice(0, -1);
  }
}

function parser(value: string, formatter: string) {
  if (!value) {
    return '';
  } else {
    return value.replace(new RegExp(formatter, 'g'), '');
  }
}
